#include<stdio.h>
#include<math.h>

const int N = 70000;
const int H = 28;
const int W = 28;
const int C = 1;
float data[N * H * W * C];
float label[N];

int DR_pow256(int a)
{
	int sum = 1;
	int i = 0;
	while (i < a)
	{
		sum = sum * 256;
		i++;
	}
	return sum;
} 

int DR_readInt(FILE *fp, int bit)
{
	char buf[255];
	int res = 0;
	int i = bit - 1;
	int tmp;
	int pows;
	while (i >= 0)
	{
		fread(buf, 1, 1, fp);
		tmp = buf[0];
		if (tmp < 0)
		{
			tmp = tmp + 256;
		}
		pows = DR_pow256(i);
		res = res + pows*tmp;
		i = i - 1;
	}
	return res;
}

int DR_scanInt(FILE *fp, int bit)
{
	int res = 0;
	int i = bit - 1;
	int tmp = 0;
	while (i >= 0)
	{
		fscanf(fp, "%c", &tmp);
		tmp = tmp % 256;
		res = res + DR_pow256(i) * tmp;
		i = i - 1;
	}
	return res;
}

void DR_intNormalize()
{
    int NHWC = N * H * W * C; // total number
    double mean = 0.0;
	double std = 0.0;
	//printf("%f %f \n", mean, std);
	int i;
	for (i = 0; i < NHWC; ++i)
	{
		mean += (double)data[i] / (NHWC);
		/*if(i > 54879500)
			printf("%s %s\n", F2S(XVal[i], buf1), F2S(mean,buf2));*/
	}
	for (i = 0; i < NHWC; ++i)
	{
		std += (double)((data[i] - mean)*(data[i] - mean)) / (NHWC);
	}
	std = sqrt(std);
	for (i = 0; i < NHWC; ++i)
	{
		data[i] = (data[i] - mean) / std;
	}
	//printf("%s %s\n", F2S(mean, buf1), F2S(std,buf2));
}

int main()
{

    FILE *fp = fopen("./dataset/train-images.idx3-ubyte", "rb");
    DR_readInt(fp, 4);
	DR_readInt(fp, 4);
	DR_readInt(fp, 4);
	DR_readInt(fp, 4);
	for (int i = 0; i < 60000;++i)
	{
        //printf("%d ", i);
        for (int j = 0; j < 784;++j)
		{
			int tmp = DR_readInt(fp, 1);
			float ftmp = (float)tmp;
            data[i * 784 + j] = ftmp; // format: 1024(R)+1024(G)+1024(B)
        }
	}
	fclose(fp);

    fp = fopen("./dataset/t10k-images.idx3-ubyte", "rb");
	DR_readInt(fp, 4);
	DR_readInt(fp, 4);
	DR_readInt(fp, 4);
	DR_readInt(fp, 4);
    for (int i = 60000; i < 70000;++i)
	{
		for (int j = 0; j < 784;++j)
		{
			int tmp = DR_readInt(fp, 1);
			float ftmp = (float)tmp;
            data[i * 784 + j] = ftmp; // format: 1024(R)+1024(G)+1024(B)
        }
	}
	fclose(fp);

    fp = fopen("./dataset/train-labels.idx1-ubyte", "rb");
	DR_readInt(fp, 4);
	DR_readInt(fp, 4);
    for (int i = 0; i < 60000;++i)
	{
		label[i] = (float)DR_readInt(fp, 1);
	}
	fclose(fp);

    fp = fopen("./dataset/t10k-labels.idx1-ubyte", "rb");
	DR_readInt(fp, 4);
	DR_readInt(fp, 4);
    for (int i = 60000; i < 70000;++i)
	{
		label[i] = (float)DR_readInt(fp, 1);
	}
	fclose(fp);
    printf("Loading final.\n");

    //DR_intNormalize();
    //printf("Normalize final.\n");

    FILE *train_data = fopen("./dataset/train_data.txt", "w");
    FILE *train_label = fopen("./dataset/train_label.txt", "w");
    for (int i = 0; i < 60000; ++i)
    {
        fprintf(train_label, "%f\n", label[i]);
        for (int j = 0; j < 784;++j)
        {
            fprintf(train_data, "%f\n", data[i * 784 + j] / 255);
        }
        //fprintf(train_data, "\n");
    }
    fclose(train_data);
    fclose(train_label);

    FILE *test_data = fopen("./dataset/test_data.txt", "w");
    FILE *test_label = fopen("./dataset/test_label.txt", "w");
    for (int i = 60000; i < 70000; ++i)
    {
        fprintf(test_label, "%f\n", label[i]);
        for (int j = 0; j < 784;++j)
        {
            fprintf(test_data, "%f\n", data[i * 784 + j] / 255);
        }
        //fprintf(test_data, "\n");
    }
    fclose(test_data);
    fclose(test_label);

    printf("Write final.\n");

    return 0;
}